/*
https://dart.cn/guides/language/effective-dart/design
 */

void main(){

}

/*
命名
命名是编写可读，可维护代码的重要部分。以下最佳实践可帮助你实现这个目标。

要 使用一致的术语。
在你的代码中，同样的东西要使用同样的名字。如果之前已经存在的 API 之外命名，并且用户已经熟知，那么请继续使用这个命

good
    pageCount         // A field.
    updatePageCount() // Consistent with pageCount.
    toSomething()     // Consistent with Iterable's toList().
    asSomething()     // Consistent with List's asMap().
    Point             // A familiar concept.


bad
    renumberPages()      // Confusingly different from pageCount.
    convertToSomething() // Inconsistent with toX() precedent.
    wrappedAsSomething() // Inconsistent with asX() precedent.
    Cartesian            // Unfamiliar to most users.



  总的目的是充分利用用户已经知道的内容。这里包括他们所了解的问题领域，所熟悉的核心库，以及你自己 API 那部分。
  基于以上这些内容，他们在使用之前，不需要学习大量的新知识。

 */

/*
  避免 缩写。
只使用广为人知的缩写，对于特有领域的缩写，请避免使用。如果要使用，请 正确的指定首字母大小写。

good
    pageCount
    buildRectangles
    IOStream
    HttpRequest

bad
    numPages    // "Num" is an abbreviation of "number (of)".
    buildRects
    InputOutputStream
    HypertextTransferProtocolRequest

 */

/*
推荐 把最具描述性的名词放到最后。
最后一个词应该是最具描述性的东西。你可以在其前面添加其他单词，例如形容词，以进一步描述该事物。

good
    pageCount             // A count (of pages).
    ConversionSink        // A sink for doing conversions.
    ChunkedConversionSink // A ConversionSink that's chunked.
    CssFontFaceRule       // A rule for font faces in CSS.

bad
    numPages                  // Not a collection of pages.
    CanvasRenderingContext2D  // Not a "2D".
    RuleFontFaceCss           // Not a CSS.

 */

/*
  好的名字往往以某一种动词作为开头：

“to be” 形式： isEnabled， wasShown， willFire。就目前来看，这些时做常见的。

一个 辅助动词: hasElements， canClose， shouldConsume， mustSave。

一个主动动词： ignoresInput， wroteFile。因为经常引起歧义，所以这种形式比较少见。 loggedResult 是一个不好的命名，因为它的意思可能是： “whether or not a result was logged” 或者 “the result that was logged”。 closingConnection 的意思可能是： “whether the connection is closing” 或者 “the connection that is closing”。 只有 当名字可以预期的时候才使用主动动词。

可以使用命令式动词来区分布尔变量名字和函数名字。一个布尔变量的名字不应该看起来像一个命令，告诉这个对象做什么事情。原因在于访问一个变量的属性并没有修改对象的状态。（如果这个属性确实修改了对象的状态，则它应该是一个函数。）

good
      isEmpty
      hasElements
      canClose
      closesWindow
      canShowPopup
      hasShownPopup

bad
    empty         // Adjective or verb?
    withElements  // Sounds like it might hold elements.
    closeable     // Sounds like an interface.
                  // "canClose" reads better as a sentence.
    closingWindow // Returns a bool or a window?
    showPopup     // Sounds like it shows the popup.

 */

/*
 考虑 省略命名布尔参数的动词。
提炼于上一条规则。对于命名布尔参数，没有动词的名称通常看起来更加舒服。

good
    Isolate.spawn(entryPoint, message, paused: false);
    var copy = List.from(elements, growable: true);
    var regExp = RegExp(pattern, caseSensitive: false);


 */

/*
考虑 为布尔属性或变量取“肯定”含义的名字。
大多数布尔值名称具有概念形式上的“肯定”和“否定”，前者感觉更像是基本描述，后者是对基本描述的否定，例如： “open” 和 “closed”， “enabled” 和 “disabled”，等等。
通常后者的名称字面上有个前缀，用来否定前者： “visible” 和 “in-visible”， “connected” 和 “dis-connected”， “zero” 和 “non-zero”。

当选择 true 代表两种情况中的其中一种情况在布尔的两种情况中，当选择 true 代表其中一种情况，或使用这种情况作为属性名称时，更倾向使用“肯定”或基本描述的方式。
布尔成员通常嵌套在逻辑表达式中，包括否定运算符。如果属性本身读起来想是个“否定”的，这将让读者耗费更多精力去阅读双重否定及理解代码的含义。

good
    if (socket.isConnected && database.hasData) {
      socket.write(database.read());
    }

bad
    if (!socket.isDisconnected && !database.isEmpty) {
      socket.write(database.read());
    }



 对于一些属性，没有明显的“肯定”形式。文档已经刷新 “saved” 到磁盘，或者 “un-changed”？文档还未属性 “un-saved” 到磁盘，或者 “changed”？在模棱两可的情况下，倾向于选择不太可能被用户否定或较短的名字。

例外: “否定”用户绝大多数用到的形式。选择「肯定」方式，将会迫使在他们到处使用 ! 对属性进行取反操作。这样相反，属性应该使用「否定」形式进行命名。

 */



/*

推荐 使用命令式动词短语来命名带有副作用的函数或者方法。
函数通常返回一个结果给调用者，并且执行一些任务或者带有副作用。在像 Dart 这种命令式语言中，调用函数通常为了实现其副作用：可能改变了对象的内部状态、产生一些输出内容、或者和外部世界沟通等。

这种类型的成员应该使用命令式动词短语来命名，强调该成员所执行的任务。

good
    list.add('element');
    queue.removeFirst();
    window.refresh();

这样，调用的方法读起来会让人觉得是一个执行命令。

考虑 使用名词短语或者非命令式动词短语命名返回数据为主要功能的方法或者函数。
虽然这些函数可能也有副作用，但是其主要目的是返回一个数据给调用者。如果该函数无需参数通常应该是一个 getter 。有时候获取一个属性则需要一些参数，比如， elementAt() 从集合中返回一个数据，但是需要一个指定返回那个数据的参数。

在语法上看这是一个函数，其实严格来说其返回的是集合中的一个属性，应该使用一个能够表示该函数返回的是什么的词语来命名。

good
    var element = list.elementAt(3);
    var first = list.firstWhere(test);
    var char = string.codeUnitAt(4);

这条规则比前一条要宽松一些。有时候一些函数没有副作用，但仍然使用一个动词短语来命名，例如： list.take() 或者 string.split()。


 */

/*
  考虑 使用命令式动词短语命名一个函数或方法，若果你希望它的执行能被重视。
当一个成员产生的结果没有额外的影响，它通常应该使用一个 getter 或者一个名词短语描述来命名，用于描述它返回的结果。
但是，有时候执行产生的结果很重要。它可能容易导致运行时故障，或者使用重量级的资源（例如，网络或文件 I/O）。
在这种情况下，你希望调用者考虑成员在进行的工作，这时，为成员提供描述该工作的动词短语。

var table = database.downloadData();
var packageVersions = packageGraph.solveConstraints();


但请注意，此准则比前两个更宽松。操作执行工作的实现细节通常与调用这无关，并且性能和健壮性是随时间经常改变的。
大多数情况下，根据成员为调用者做了“什么”来命名，而不是“如何”做。

 */



/*

避免 在方法命名中使用 get 开头。
在大多数情况下，getter 方法名称中应该移除 get 。例如，定义一个名为 breakfastOrder 的 getter 方法，来替代名为 getBreakfastOrder() 的方法。

即使成员因为需要传入参数或者 getter 不适用，而需要通过方法来实现，也应该避免使用 get 开头。与之前的准则一样：

如果调用者主要关心的是方法的返回值，只需删除 get 并使用 名词短语 命名，如 breakfastOrder() 。

如果调用者关心的是正在完成的工作，请使用 动名词短语 命名，这种情况下应该选择一个更能准确描述工作的动名词，而不是使用 get 命名，如 create， download， fetch， calculate， request， aggregate，等等。



推荐 使用 to___() 来命名把对象的状态转换到一个新的对象的函数。
Linter rule: use_to_and_as_if_applicable

一个转换函数返回一个新的对象，里面包含一些原对象的状态，但通常新对象的形式或表现方式与原对象不同。核心库有一个约定，这些类型结果的方法名应该以 to 作为开头。

如果要定义一个转换函数，遵循该约定是非常有益的。

good
    list.toSet();
    stackTrace.toString();
    dateTime.toLocal();

 */


/*

  推荐 使用 as___() 来命名把原来对象转换为另外一种表现形式的函数。
Linter rule: use_to_and_as_if_applicable

转换函数提供的是“快照功能”。返回的对象有自己的数据副本，修改原来对象的数据不会改变返回的对象中的数据。另外一种函数返回的是同一份数据的另外一种表现形式，返回的是一个新的对象，但是其内部引用的数据和原来对象引用的数据一样。修改原来对象中的数据，新返回的对象中的数据也一起被修改。

这种函数在核心库中被命名为 as___()。

good
    var map = table.asMap();
    var list = bytes.asFloat32List();
    var future = subscription.asFuture();

 */


/*
  避免 在方法或者函数名称中描述参数。
  在调用代码的时候可以看到参数，所以无需再次显示参数了。

good
    list.add(element);
    map.remove(key);

bad
    list.addElement(element)
    map.removeKey(key)

但是，对于具有多个类似的函数的时候，使用参数名字可以消除歧义，这个时候应该带有参数名字：

good
    map.containsKey(key);
    map.containsValue(value);

 */


/*

 要 在命名参数时，遵循现有的助记符约定。
单字母命名没有直接的启发性，但是几乎所有通用类型都使用时情况就不一样了。幸运的是，它们大多数以一致的助记方式在使用，这些约定如下：

E 用于集合中的 元素 类型:
good
    class IterableBase<E> {}
    class List<E> {}
    class HashSet<E> {}
    class RedBlackTree<E> {}


K 和 V 分别用于关联集合中的 key 和 value 类型：

good
    class Map<K, V> {}
    class Multimap<K, V> {}
    class MapEntry<K, V> {}

R 用于函数或类方法的 返回值 类型。这种情况并不常见，但有时会出现在typedef中，或实现访问者模式的类中：

good
    abstract class ExpressionVisitor<R> {
      R visitBinary(BinaryExpression node);
      R visitLiteral(LiteralExpression node);
      R visitUnary(UnaryExpression node);
    }



除此以外，对于具有单个类型参数的泛型，如果助记符能在周围类型中明显表达泛型含义，请使用T，S 和 U 。这里允许多个字母嵌套且不会与周围命名产生歧义。例如：

class Future<T> {
  Future<S> then<S>(FutureOr<S> onValue(T value)) => ...
}

这里，通常 then<S>() 方法使用 S 避免 Future<T> 中的 T 产生歧义。

如果上述情况都不合适，则可以使用另一个单字母助记符名称或描述性的名称：

good
    class Graph<N, E> {
      final List<N> nodes = [];
      final List<E> edges = [];
    }

    class Graph<Node, Edge> {
      final List<Node> nodes = [];
      final List<Edge> edges = [];
    }



 */


